package cs470.agent;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.plaf.PanelUI;

import cs470.kalman.KalmanFilter;
import cs470.kalman.Matrix;

import Code.BZRClient;
import Code.EnemyTank;
import Code.Point;
import Code.Tank;

public class KalmanAgent extends AbstractAgent {

	private final static double CLOSE_ENOUGH = .05;
	
	long nextTime = 0L;
	long nextShot = 0L;
	Point myLocation = Point.ZERO;
	final KalmanFilter filter; 
	
	long murderTime;
	boolean isMurdered;
	
	public KalmanAgent(BZRClient client, final KalmanFilter filter) {
		super(client);
		this.filter = filter;
	}
	
	public void run() {
		setRunning(true);
		
		murderTime = System.currentTimeMillis();
		
		while(isRunning()) {
			//if(System.currentTimeMillis() >= nextTime) {
				final long time = System.currentTimeMillis();
			
				final Map<String, List> map = bzrClient.getAllTanks();
				
				final List<Tank> tanks = new ArrayList<Tank>(map.get("mytanks"));
				final List<EnemyTank> enemyTanks = new ArrayList<EnemyTank>(map.get("othertanks"));

				if(tanks.isEmpty() || enemyTanks.isEmpty()) {
					System.out.println("no tanks");
					continue;
				}
				//TODO: get point at which I need to shoot.
				final Tank tank = tanks.get(0);
				
				final EnemyTank enemy = enemyTanks.get(0);
				if(enemy.getStatus().equals("alive")) {
					isMurdered = true;
					
					final Point enemyLocation = enemy.getLocation();
					
					final Matrix observation = Matrix.getMatrixFromPoint(enemyLocation);
					
					final Point point = filter.update(observation, tank.getLocation());
					
					final double desiredAngle = Math.atan2(point.getY() - tank.getY(), point.getX() - tank.getX());
	
					//System.out.println(tank.getAngle() - desiredAngle);
					if(Math.abs(tank.getAngle() - desiredAngle) < CLOSE_ENOUGH) {
						turnR(tank, 0);
						if(System.currentTimeMillis() > nextShot) {
							double distance = point.calcDistance(tank.getLocation());
							shoot();
							nextShot = (long) (System.currentTimeMillis() + 1000L/distance + .00001); //Modify by the distance
						}
					} else {
						turnR(tank, desiredAngle - tank.getAngle());
					}
				
				} else {
					if(isMurdered) {
						long startTime = murderTime;
						murderTime = System.currentTimeMillis();
						System.out.println("Time until death: " + (murderTime - startTime));
						isMurdered = false;
					}
				}
				long diff = 500L - System.currentTimeMillis() - time;
				if(diff>0)
				pause(diff);
//				final double angle = angle(tank, enemyLocation);
//				System.out.println(angle);
//				
//				turnR(tank, angle);
//				shoot();
				
				//nextTime = System.currentTimeMillis() + 100L;
			//}
		}
	}
	
	private double angle(Tank tank, Point target) {
		Point tankLocation = tank.getLocation();
		double targetAngle = Math.atan2(target.getY() - tankLocation.getY(), target.getX() - tankLocation.getX());
		
		targetAngle -= tank.getAngle();
		
		targetAngle -= 2*Math.PI * (int)(targetAngle/(2*Math.PI));
		if(targetAngle <= -Math.PI) {
			targetAngle += 2*Math.PI;
		} else if(targetAngle > Math.PI) {
			targetAngle -= 2*Math.PI; 
		}
		
		return targetAngle;
	}
	
}
